<script lang="ts" setup>
import axios from 'axios'
import { onMounted, ref, render } from 'vue'

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

const dataview = ref(null)

onMounted(async () => {
  const res = await axios.get('/0_nodes_SPE10.txt')
  const data = res.data.split('\n').map((line) => line.split(','))

  // scene camera renderer
  const scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000)
  const renderer = new THREE.WebGLRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight - 100)

  const material = new THREE.PointsMaterial({ color: 0x00ff00, size: 0.001 })

  const vecs = []

  let min_x = 10e10,
    max_x = -10e10
  let min_y = 10e10,
    max_y = -10e10
  let min_z = 10e10,
    max_z = -10e10

  function isTop(z) {
    return z === max_z ? true : false
  }

  function isRound() {
    return
  }

  for (let i = 0; i < data.length; i++) {
    const x = parseFloat(data[i][0])
    const y = parseFloat(data[i][1])
    const z = parseFloat(data[i][2])

    min_x = min_x > x ? x : min_x
    min_y = min_y > y ? y : min_y
    min_z = min_z > z ? z : min_z
    max_x = max_x < x ? x : max_x
    max_y = max_y < y ? y : max_y
    max_z = max_z < z ? z : max_z
  }

  console.log(min_x, max_x, min_y, max_y, min_z, max_z)
  console.log('data length: ', data.length)

  const aspect_x = 0.015
  const aspect_y = 0.015
  const aspect_z = 0.015

  for (let i = 0; i < data.length; i++) {
    const x = parseFloat(data[i][0])
    const y = parseFloat(data[i][1])
    const z = parseFloat(data[i][2])

    // filter out the top layer
    if (isTop(z)) {
      vecs.push((x - min_x) * aspect_x)
      vecs.push((y - min_y) * aspect_y)
      vecs.push((z - min_z) * aspect_z)
    }
  }

  const geometry = new THREE.BufferGeometry()
  geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(vecs), 3))
  const point = new THREE.Points(geometry, material)
  scene.add(point)

  // orbit controls

  const controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
  controls.enablePan = true

  function getColorFromValue(value) {
    const green = new THREE.Color(0x00ff00)
    const red = new THREE.Color(0xff0000)
    return green.lerp(red, value)
  }

  // axes
  const axesHelper = new THREE.AxesHelper(
    Math.max(max_x - min_x, max_y - min_y, max_z - min_z) * 0.01,
  )
  scene.add(axesHelper)

  // camera
  camera.position.set(5, -24, 12)
  camera.lookAt(0, 0, 0)

  // render dom
  dataview.value.appendChild(renderer.domElement)

  // load boxes
  const res_boxes = await axios.get('/0_boxs_SPE10.txt')
  const data_boxes = res_boxes.data.split('\n').map((line) => line.split(','))

  function getPoint(pxyz) {
    const x = (pxyz[0] - min_x) * aspect_x
    const y = (pxyz[1] - min_y) * aspect_y
    const z = (pxyz[2] - min_z) * aspect_z * 10
    const p_vec = new Float32Array([x, y, z])
    const p_geometry = new THREE.BufferGeometry()
    p_geometry.setAttribute('position', new THREE.BufferAttribute(p_vec, 3))

    const r_material = material.clone()
    r_material.color = new THREE.Color(0x00ff00)
    r_material.size = 0.1
    const point = new THREE.Points(p_geometry, r_material)

    return point
  }

  let points_stack = []
  const color = new THREE.Color()
  let colors = []

  for (let i = 0; i < data_boxes.length; i++) {
    if (i > 1000) {
      break
    }
    const p1 = parseInt(data_boxes[i][0])
    const p2 = parseInt(data_boxes[i][1])
    const p3 = parseInt(data_boxes[i][2])
    const p4 = parseInt(data_boxes[i][3])
    const p5 = parseInt(data_boxes[i][4])
    const p6 = parseInt(data_boxes[i][5])
    const p7 = parseInt(data_boxes[i][6])
    const p8 = parseInt(data_boxes[i][7])

    // get p's x y z
    const p1_xyz = data[p1 - 1].slice(0, 3).map(Number)
    const p2_xyz = data[p2 - 1].slice(0, 3).map(Number)
    const p3_xyz = data[p3 - 1].slice(0, 3).map(Number)
    const p4_xyz = data[p4 - 1].slice(0, 3).map(Number)
    const p5_xyz = data[p5 - 1].slice(0, 3).map(Number)
    const p6_xyz = data[p6 - 1].slice(0, 3).map(Number)
    const p7_xyz = data[p7 - 1].slice(0, 3).map(Number)
    const p8_xyz = data[p8 - 1].slice(0, 3).map(Number)

    // console.log('boxes', i, data_boxes[i], p5_xyz, p6_xyz, p7_xyz, p8_xyz)

    // draw points

    const point1 = getPoint(p1_xyz)
    const point2 = getPoint(p2_xyz)
    const point3 = getPoint(p3_xyz)
    const point4 = getPoint(p4_xyz)
    const point5 = getPoint(p5_xyz)
    const point6 = getPoint(p6_xyz)
    const point7 = getPoint(p7_xyz)
    const point8 = getPoint(p8_xyz)
    scene.add(point1)
    scene.add(point2)
    scene.add(point3)
    scene.add(point3)
    scene.add(point5)
    scene.add(point6)
    scene.add(point7)
    scene.add(point8)

    // // draw area
    // const material_area = new THREE.LineBasicMaterial({ color: 0x00ff00 })
    // const line_geometry = new THREE.BufferGeometry()
    // const line_vertices = [
    //   (p1_xyz[0] - min_x) * aspect_x,
    //   (p1_xyz[1] - min_y) * aspect_y,
    //   (p1_xyz[2] - min_z) * aspect_z * 10,
    //   (p2_xyz[0] - min_x) * aspect_x,
    //   (p2_xyz[1] - min_y) * aspect_y,
    //   (p2_xyz[2] - min_z) * aspect_z * 10,
    //   (p3_xyz[0] - min_x) * aspect_x,
    //   (p3_xyz[1] - min_y) * aspect_y,
    //   (p3_xyz[2] - min_z) * aspect_z * 10,
    // ]
    // line_geometry.setAttribute(
    //   'position',
    //   new THREE.BufferAttribute(new Float32Array(line_vertices), 3),
    // )
    // const line = new THREE.Line(line_geometry, material_area)
    // scene.add(line)

    const triangle_vertices = [
      (p1_xyz[0] - min_x) * aspect_x,
      (p1_xyz[1] - min_y) * aspect_y,
      (p1_xyz[2] - min_z) * aspect_z * 10,
      (p2_xyz[0] - min_x) * aspect_x,
      (p2_xyz[1] - min_y) * aspect_y,
      (p2_xyz[2] - min_z) * aspect_z * 10,
      (p3_xyz[0] - min_x) * aspect_x,
      (p3_xyz[1] - min_y) * aspect_y,
      (p3_xyz[2] - min_z) * aspect_z * 10,
      (p3_xyz[0] - min_x) * aspect_x,
      (p3_xyz[1] - min_y) * aspect_y,
      (p3_xyz[2] - min_z) * aspect_z * 10,
      (p4_xyz[0] - min_x) * aspect_x,
      (p4_xyz[1] - min_y) * aspect_y,
      (p4_xyz[2] - min_z) * aspect_z * 10,
      (p1_xyz[0] - min_x) * aspect_x,
      (p1_xyz[1] - min_y) * aspect_y,
      (p1_xyz[2] - min_z) * aspect_z * 10,
    ]

    const vx = 0.3
    const vy = 0.3
    const vz = 0.4
    color.setRGB(vx, vy, vz, THREE.SRGBColorSpace)
    colors.push(color.r, color.g, color.b)
    colors.push(color.r, color.g, color.b)
    points_stack = points_stack.concat(triangle_vertices)
  }

  // 绘制三角形
  const material_triangle = new THREE.MeshBasicMaterial({ color: 0x00ff00})

  const triangle_geometry = new THREE.BufferGeometry()
  triangle_geometry.setAttribute(
    'position',
    new THREE.BufferAttribute(new Float32Array(points_stack), 3),
  )

  const triangle = new THREE.Mesh(triangle_geometry, material_triangle)
  scene.add(triangle)

  function animate() {
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
    // console.log(camera.position)
  }
  animate()
})
</script>

<template>
  <div>
    <!-- {{ data }} -->
    <div ref="dataview"></div>
  </div>
</template>

<style lang="scss" scoped></style>
